package code.juc.stopThread.volatiledemo;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * 演示使用volatile的局限part2：
 * 线程陷入阻塞时, volatile是无法停止线程的。
 * <p>
 * 此例中，生产者的生产速度很快，但是，消费者的消费速度很慢，所以，阻塞队列满了以后，生产者会阻塞，
 * 等待消费者的进一步消费。
 *
 * 结果：无法停止线程. canceled确实被设置成为了true.
 *
 * 原因：在于存在wait的时候, 是无法打断wait状态; 无法执行到判断语句, 因此, 无法停止线程.
 */
public class WrongWayVolatileCantStopThread {

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue storage = new ArrayBlockingQueue(10);

        Producer producer = new Producer(storage);
        Thread producerThread = new Thread(producer);
        producerThread.start();
        Thread.sleep(1000);

        Consumer consumer = new Consumer(storage);
        while (consumer.needMoreNums()) {
            System.out.println("消费: " + storage.take());
        }
        System.out.println("消费者不需要再消费啦!");

        // 让生产者停止生产数据.
        producer.canceled = true;
        System.out.println(producer.canceled);
    }
}

/**
 * 生产者
 */
class Producer implements Runnable {

    public volatile boolean canceled = false;

    private BlockingQueue storage;

    public Producer(BlockingQueue storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        int num = 0;
        try {
            while (num < Integer.MAX_VALUE / 2 && !canceled) {
                if (num % 100 == 0) {
                    storage.put(num);
                    System.out.println(num + " is mod 100, 且放入到了队列中!");
                }

                num++;
            }
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            System.out.println("生产者已经停止运行!");
        }
    }
}

/**
 * 消费者
 */
class Consumer {

    BlockingQueue storage;

    public Consumer(BlockingQueue storage) {
        this.storage = storage;
    }

    public boolean needMoreNums() {
        if (Math.random() > 0.95) {
            return false;
        }

        return true;
    }
}